'use strict'

const log = require('../log.js')

var Promise = require('bluebird')
var _ = require('lodash')	//_.extend(form, permanent)  引用的库
var util = require('./util')
var fs = require('fs')

//使用bluebird将request库的所有异步方法编译成promise形式，会自动加上Async后缀
var request = Promise.promisify(require('request'))	//对request进行Promise化处理

var prefix = 'https://api.weixin.qq.com/cgi-bin/'
var api = {
	accessToken: prefix + 'token?grant_type=client_credential',
	temporary:{
		upload: prefix + 'media/upload?', //临时素材上传
		fetch: prefix + 'media/get?'	//获取临时素材

	},
	permanent: {
		upload: prefix + 'material/add_material?', //新增其他类型永久素材
		uploadNews: prefix + 'material/add_news?', //新增永久图文素材
		uploadNewsPic: prefix + 'media/uploadimg?', //上传图文消息内的图片获取URL 
		fetch: prefix + 'material/get_material?',	//获取永久素材
		del: prefix + 'material/del_material?',
		update: prefix + 'material/update_news?',
		count: prefix + 'material/get_materialcount?',
		batch: prefix + 'material/batchget_material?'
	},
	group: {
		create: prefix + 'tags/create?',	//创建用户标签
		fetch: prefix + 'tags/get?',		//获取公众号已创建的标签
		update: prefix + 'tags/update?',	//编辑标签
		del: prefix + 'tags/delete?',		//删除标签
		fetchUsers: prefix + 'user/tag/get?',	//获取标签下粉丝列表
		batchTags: prefix + 'tags/members/batchtagging?',	//批量为用户打标签
		batchUnTags: prefix + 'tags/members/batchuntagging?',	//批量为用户取消标签
		fetchIdList: prefix + 'tags/getidlist?',		//获取用户身上的标签列表
		updateRemark: prefix + 'user/info/updateremark?',	//设置用户备注名
		
		fetchUserInfo: prefix + 'user/info?',		//获取用户基本信息（包括UnionID机制）
		fetchUserList: prefix + 'user/get?',			//获取用户列表
		fetchBlackList: prefix + 'tags/members/getblacklist?',	//获取公众号的黑名单列表
		batchBlackList: prefix + 'tags/members/batchblacklist?',	//拉黑用户
		batchUnBlackList: prefix + 'tags/members/batchunblacklist?'	//取消拉黑用户
	},
	message: {
	  	// 设置所属行业  POST  template/api_set_industry?access_token=ACCESS_TOKEN
		setIndustry: prefix + 'template/api_set_industry?',

		// 获取设置的行业信息  GET  template/get_industry?access_token=ACCESS_TOKEN
		
		// 获得模板ID  POST  template/api_add_template?access_token=ACCESS_TOKEN
		

		// 获取模板列表  GET  template/get_all_private_template?access_token=ACCESS_TOKEN
		

		// 删除模板  POST  template/del_private_template?access_token=ACCESS_TOKEN


		// 发送模板消息  POST  message/template/send?access_token=ACCESS_TOKEN
		sendMessageTpl: prefix + 'message/template/send?'

		// 事件推送
	},
	ticket: {
		get: prefix + 'ticket/getticket?'
	}

}
var msgtpl = {
	// 设置所属行业  POST  template/api_set_industry?access_token=ACCESS_TOKEN
	
	// 获取设置的行业信息  GET  template/get_industry?access_token=ACCESS_TOKEN
	
	// 获得模板ID  POST  template/api_add_template?access_token=ACCESS_TOKEN
	

	// 获取模板列表  GET  template/get_all_private_template?access_token=ACCESS_TOKEN
	

	// 删除模板  POST  template/del_private_template?access_token=ACCESS_TOKEN


	// 发送模板消息  POST  message/template/send?access_token=ACCESS_TOKEN
	send: prefix + 'message/template/send?'

	// 事件推送


}

//构造函数
function Wechat(opts){
	var that = this
	this.appID = opts.appID
	this.appsecret = opts.appsecret
	this.getAccessToken = opts.getAccessToken
	this.saveAccessToken = opts.saveAccessToken

	this.getTicket = opts.getTicket
// log.info(opts)
	this.saveTicket = opts.saveTicket

	this.fetchAccessToken()
}


//获取票据的方法
Wechat.prototype.fetchAccessToken = function(data){
	var that = this

	/*if(this.access_token && this.expires_in){
		if(this.isValiAccessToken(this)){
			return Promise.resolve(this)
		}
	}*/

	//直接从文件读取

	return this.getAccessToken()
		.then(function(data){
			try{
				data = JSON.parse(data)
			}
			catch(e){
				return that.updateAccessToken()
			}

			//判断 票据是否合法，是否过期
			if(that.isValiAccessToken(data)){
				return Promise.resolve(data)
			}
			else{
				return that.updateAccessToken()
			}
		})
		.then(function(data){			
			that.access_token = data.access_token	//获取票据
			that.expires_in = data.expires_in	//过期时间
			that.saveAccessToken(data)

			return Promise.resolve(data)
		})
}
//采用http GET方式请求获得jsapi_ticket（有效期7200秒，开发者必须在自己的服务全局缓存jsapi_ticket）
Wechat.prototype.fetchTicket = function(access_token){
	var that = this
	//直接从文件读取

	return this.getTicket()
		.then(function(data){
			try{
				data = JSON.parse(data)
			}
			catch(e){
				return that.updateTicket(access_token)
			}
			//判断 票据是否合法，是否过期
			if(that.isValiTicket(data)){
				return Promise.resolve(data)
			}
			else{
				return that.updateTicket(access_token)
			}
		})
		.then(function(data){		
			that.saveTicket(data)

			return Promise.resolve(data)
		})
}

//增加验证票据的方法
Wechat.prototype.isValiAccessToken = function(data){
	//判断是否有值，是否有票据，是否时间过期
	if(!data || !data.access_token || !data.expires_in){
		return false
	}
	var access_token = data.access_token
	var expires_in = data.expires_in
	var now = (new Date().getTime())	//当前日期

	//判断当前日期是否小于过期日期
	if(now < expires_in){
		return true
	}
	else{
		return false
	}
}

Wechat.prototype.isValiTicket = function(data){
	//判断是否有值，是否有票据，是否时间过期
	if(!data || !data.ticket || !data.expires_in){
		return false
	}
	var ticket = data.ticket
	var expires_in = data.expires_in
	var now = (new Date().getTime())	//当前日期

	//判断当前日期是否小于过期日期
	if(ticket && now < expires_in){
		return true
	}
	else{
		return false
	}
}

// 增加票据更新的方法
Wechat.prototype.updateAccessToken = function(){
	var appID = this.appID
	var appsecret = this.appsecret
	var url = api.accessToken + '&appid=' + appID + '&secret=' + appsecret

	//封装
	return new Promise(function(resolve, reject){
		//向服务器发送GET或POST请求
		request({url: url, json: true}).then(function(response){
			var data = response.body
			var now = (new Date().getTime())
			var expires_in = now + (data.expires_in - 20) * 1000	//更新过期时间：当前时间加上过期时间 乘以 1000毫秒

			data.expires_in = expires_in	//新的票据时间赋值给 data
			resolve(data)
		})

	})

} 

Wechat.prototype.updateTicket = function(access_token){
	var url = api.ticket.get + 'access_token=' + access_token + '&type=jsapi'
// log.info(url)
	//封装
	return new Promise(function(resolve, reject){
		//向服务器发送GET或POST请求
		request({url: url, json: true}).then(function(response){
			var data = response.body
			var now = (new Date().getTime())
			var expires_in = now + (data.expires_in - 20) * 1000	//更新过期时间：当前时间加上过期时间 乘以 1000毫秒

			data.expires_in = expires_in	//新的票据时间赋值给 data
			resolve(data)
		})

	})

} 


// 增加素材上传方法
Wechat.prototype.uploadMaterial = function(type, material, permanent){
	var that = this
	var form = {}	//空对象

	var uploadUrl = api.temporary.upload

	if(permanent){
		uploadUrl = api.permanent.upload

		_.extend(form, permanent)	//让form能兼容所有类型，包括图文，所以需要继承

	}

	if(type === 'pic'){
		uploadUrl = api.permanent.uploadNewsPic

	}


	if(type === 'news'){
		uploadUrl = api.permanent.uploadNews
		form = material  //需要由一个数组form，如果是图文的话，这个素材就是图文的数据，material就是一个图文的数组

	}else{
		//如果material不是数组，则就认为他是一个文件的路径
		form.media = fs.createReadStream(material)
	}

	

	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = uploadUrl + 'access_token='+ data.access_token

				if(!permanent){
					//permanent 为空，则不是永久函数
					url += '&type=' + type	
								
				}
				else{
					form.access_token = data.access_token
	
				}

				var options = {
					method: 'POST',
					url: url,
					json: true
				}

				if( type === 'news'){
					options.body = form 	//如果是图文的，我们上传的是body


				}
				else{
					options.formData = form
				}

				//向服务器发送GET或POST请求
				request(options).then(function(response){
					// log.info(response.body)
					var _data = response.body
					
					if(_data){
						resolve(_data)
					}else{
						throw new Error('Upload material fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//获取素材
Wechat.prototype.fetchMaterial = function(mediaId, type, permanent){
	var that = this
	var fetchUrl = api.temporary.fetch

	if(permanent){
		fetchUrl = api.permanent.fetch

	}

	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = fetchUrl + 'access_token='+ data.access_token

				var options = {method: 'POST', url: url, json: true}
				var form = []
				if(permanent){
					form.media_id= mediaId
log.info(mediaId)					
					form.access_token= data.access_token
					options.body = form
			
				}
				else{
					//如果不是永久素材，并且又是视频，则将https转换成http
					if(type === 'video'){
						url = url.replace('https://', 'http://')
					}
					url  += '&media_id=' + mediaId
				}

				if(type === 'news' || type === 'video'){
					
					//向服务器发送GET或POST请求
					request(options).then(function(response){

						var _data = response.body
						
						if(_data){
							resolve(_data)
						}else{
							throw new Error('Fetch material fails;')
						}
					})
					.catch(function(err){	//捕获异常
						reject(err)
					})
				}
				else{
					resolve(url)
				}
				

			})
	})

} 

//删除永久素材
Wechat.prototype.deleteMaterial = function(mediaId){
	var that = this
	var form = {
		media_id: mediaId
	}	//空对象

	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.permanent.del + 'access_token='+ data.access_token + '&media_id=' + mediaId
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					// log.info(response.body)
					var _data = response.body
					
					if(_data){
						resolve(_data)
					}else{
						throw new Error('Delete material fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//更新永久素材
Wechat.prototype.updateMaterial = function(mediaId, news){
	var that = this
	var form = {
		media_id: mediaId
	}	//空对象

	_.extend(form, news)


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.permanent.update + 'access_token='+ data.access_token + '&media_id=' + mediaId
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					// log.info(response.body)
					var _data = response.body
					
					if(_data){
						resolve(_data)
					}else{
						throw new Error('Update material fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//获取素材数量
Wechat.prototype.countMaterial = function(){
	var that = this

	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.permanent.count + 'access_token='+ data.access_token
				
				//向服务器发送GET或POST请求
				request({method: 'GET', url: url, json: true}).then(function(response){
					// log.info(response.body)
					var _data = response.body
					
					if(_data){
						resolve(_data)
					}else{
						throw new Error('Counts material fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

}

//获取素材列表
Wechat.prototype.batchMaterial = function(options){
	var that = this

	options.type = options.type || 'image'
	options.offset = options.offset || 0
	options.count = options.count || 1

	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.permanent.batch + 'access_token='+ data.access_token
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body:options, json: true}).then(function(response){

					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Batch material fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//创建用户标签
Wechat.prototype.createTags = function(name){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.create + 'access_token='+ data.access_token
				var options = {
					tag:{
						name: name
					}
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body:options, json: true}).then(function(response){

					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Create tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//获取公众号已创建的标签
Wechat.prototype.fetchTags = function(name){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.fetch + 'access_token='+ data.access_token
				var options = {
					tag:{
						name: name
					}
				}
				
				//向服务器发送GET或POST请求
				request({method: 'GET', url: url, json: true}).then(function(response){

					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Fetch tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//编辑标签
Wechat.prototype.updateTags = function(tagId, name){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.update + 'access_token='+ data.access_token
				var form = {
					tag:{
						id: tagId,
						name: name
					}
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){

					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//删除标签
Wechat.prototype.delTags = function(optionID){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.del + 'access_token='+ data.access_token
				var options = {
					tag:{
						id: optionID
					}
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: options, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 
//获取标签下粉丝列表
Wechat.prototype.fetchUsers = function(tagID, openID){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.fetchUsers + 'access_token='+ data.access_token
				var form = {
					tagid: tagID,
					next_openid: openID
				}
log.info(url)				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
log.info(response)					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//批量为用户打标签 flag = Y， 或取消标签 flag = N
Wechat.prototype.batchTags = function( openIDs,tagID, flag){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.batchTags + 'access_token='+ data.access_token

				if(flag && flag === 'N'){
					var url = api.group.batchUnTags + 'access_token='+ data.access_token
				}
				
				var form = {
					openid_list: openIDs,
					tagid: tagID
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('batchTags tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//获取用户身上的标签列表
Wechat.prototype.fetchIdList = function(openID){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.fetchIdList + 'access_token='+ data.access_token
				var form = {
					openid: openID
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//批量更新用户身上的标签列表
Wechat.prototype.updateRemark = function(openID, name){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.updateRemark + 'access_token='+ data.access_token
				var form = {
					openid: openID,
					remark: name
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 

//获取用户基本信息（包括UnionID机制）
Wechat.prototype.fetchUserInfo = function(openID, type){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.fetchUserInfo + 'access_token='+ data.access_token + '&openid='+ openID +'&lang=zh_CN'
								
				//向服务器发送GET或POST请求
				request({method: 'GET', url: url, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 
//获取用户列表 list
Wechat.prototype.fetchUserList = function(openID){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.group.fetchUserList + 'access_token='+ data.access_token
				//判断type不为空，且类型是 list
				if(openID){
					url += '&next_openid=' + openID
				}
				
				//向服务器发送GET或POST请求
				request({method: 'GET', url: url, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Update tags fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 
//设置所属行业
Wechat.prototype.setIndustry = function(){
	var that = this


	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.message.setIndustry + 'access_token='+ data.access_token
				
				var form = {
					industry_id1: 13
				}
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body:form, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Set Industry fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 
//获取设置的行业信息
Wechat.prototype.fetchIndustry = function(){
	var that = this
	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.message.fetchIndustry + 'access_token='+ data.access_token
				
				
				//向服务器发送GET或POST请求
				request({method: 'GET', url: url, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Fetch Industry fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})
} 
//获得模板ID
Wechat.prototype.fetchTemplate = function(){
	var that = this
	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.message.fetchTemplate + 'access_token='+ data.access_token
				
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Fetch Template fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})
} 
//发送消息模板 lvj
Wechat.prototype.sendMessageTpl = function(openID, tplID, url, data){
	var that = this
	//封装
	return new Promise(function(resolve, reject){

		that
			.fetchAccessToken()
			.then(function(data){
				var url = api.message.sendMessageTpl + 'access_token='+ data.access_token
				
				// form = {}
				// form.touser=  openID
				// form.template_id= tplID
				// form.url= url
				// form.data = data

				var form  = {
					touser: openID,
					template_id: tplID,
					url: url,
					data: {
						result: {
							value: '尊敬的客户：\n您有[ 1 ]个快递包裹已经到达<汤西种子站>，请尽快过来拿取。\n\n',
							color: '#000'
						},
						kdInfo: {
							value: '[百世]123456789;[顺丰]123456789;[天天]123456789\n\n\n',
							color: '#000'
						},
						kdTime: {
							value: '10月16日14:42\n',
							color: '#000'
						},
						remark: {
							value: '收到此信息后，请回复“收到”，感谢您的反馈！',
							color: '#ff0000'
						}
					}
				}
					
log.info(form)
				//向服务器发送GET或POST请求
				request({method: 'POST', url: url, body: form, json: true}).then(function(response){
					
					var _data = response.body
					
					if(_data){
						resolve(_data)

					}else{
						throw new Error('Fetch Template fails;')
					}
				})
				.catch(function(err){	//捕获异常
					reject(err)
				})
			})
	})

} 


Wechat.prototype.reply = function(){
	var content = this.body
	var message = this.weixin
// log.info(content)
	var xml = util.tpl(content, message)

	this.status = 200
	this.type = 'application/xml'
	this.body = xml
// log.info(message)
}

module.exports = Wechat